
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
	<title>YUI Library Examples: Attribute: Attribute Getters, Setters and Validators</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    	<link rel="stylesheet" type="text/css" href="../../assets/yui.css" >

<style>
    /*Supplemental CSS for the YUI distribution*/
    #custom-doc { width: 95%; min-width: 950px; }
    #pagetitle {background-image: url(../../assets/bg_hd.gif);}
/*    #pagetitle h1 {background-image: url(../../assets/title_h_bg.gif);}*/
</style>

<link rel="stylesheet" type="text/css" href="../../assets/dpSyntaxHighlighter.css">
<link type="text/css" rel="stylesheet" href="../../build/cssfonts/fonts-min.css" />
<script type="text/javascript" src="../../build/yui/yui-min.js"></script>
<style type="text/css">

    #boxParent {
        overflow:hidden;
        background-color:#004c6d;
        height:25em;
        padding:10px;
        margin:5px;
    }

    #boxParent .yui3-box p, #attrs p {
        margin:2px;
    }

    .attrs {
        border:1px solid #000;
        background-color:#cdcdcd;
        margin:5px;
    }

    .attrs .header {
        font-weight:bold;
        background-color:#aaa;
        padding:5px;
    }

    .attrs .body {
        padding:10px;
    }
 
    .attrs .body .hints li {
        padding-bottom:10px;
    }

    .attrs .footer {
        padding:0px 20px 10px 20px;
    }

    .attrs label {
        font-weight:bold;
        display:block;
        float:left;
        width:4em;
    }

    .attrs .hint {
        font-size:85%;
        color: #004c6d;
    }

    .attrs .fields {
        border-top:1px solid #aaa;
        padding:10px;
    }

    .yui3-box {
        padding:5px;
        border:1px solid #000;
        width:8em;
        height:8em;
        text-align:center;
        color:#000;
    }

    .yui3-box .color, .yui3-box .coord {
        font-family:courier;
    }

</style>

</head>
<body id="yahoo-com" class="yui3-skin-sam  yui-skin-sam">
<div id="custom-doc" class="yui-t2">
<div id="hd">
	<div id="ygunav">
		<p>
            <em>
                <a href="http://developer.yahoo.com/yui/3/">YUI 3.x Home</a> <i> - </i>	
            </em>
		</p>
		<form action="http://search.yahoo.com/search" id="sitesearchform">
            <input name="vs" type="hidden" value="developer.yahoo.com">
            <input name="vs" type="hidden" value="yuiblog.com">
		    <div id="sitesearch">
		    	<label for="searchinput">Site Search (YDN &amp; YUIBlog): </label>
			    <input type="text" id="searchinput" name="p">
			    <input type="submit" value="Search" id="searchsubmit" class="ygbt">
		    </div>
		</form>
    </div>
	<div id="ygma"><a href="../../"><img src="../../assets/logo.gif"  border="0" width="200" height="93"></a></div>
	<div id="pagetitle"><h1>YUI Library Examples: Attribute: Attribute Getters, Setters and Validators</h1></div>
</div>
<div id="bd">


	<div id="yui-main">
		<div class="yui-b">
		  <div class="yui-ge">
			  <div class="yui-u first example" id="main">

	<h2>Attribute: Attribute Getters, Setters and Validators</h2>

	<div id="example" class="promo">
	<div class="example-intro">
	The <a href="attribute-basic.html">"Basic Attribute Configuration" example</a> shows how you can add attributes to a host class, and set up default values for them using the attribute configuration object. This example explores how you can configure <code>setter</code>, <code>getter</code> and <code>validator</code> functions for individual attributes, which can be used to modify or normalize attribute values during get and set invocations, and prevent invalid values from being stored. 


	</div>	

	<div class="module example-container ">
			<div class="hd exampleHd">
			<p class="newWindowButton yui-skin-sam">
                <a href="attribute-getset_clean.html" target="_blank">View example in new window.</a>
            </p>
		</div>		<div id="example-canvas" class="bd">

		
	<!--BEGIN SOURCE CODE FOR EXAMPLE =============================== -->
	
	<div id="attrs" class="attrs">
    <div class="header">Enter new values and click the "Set" buttons</div>
    <div class="body">
        <ul class="hints">
            <li>Try entering valid and invalid values for x, y; or values which attempt to position the box outside it's parent (parent box co-ordinates are displayed next to the text box).</li>
            <li>Try entering rgb, hex or keyword color values [ <code>rgb(255,0,0)</code>, <code>#ff0000</code>, <code>red</code> ].</li>
        </ul>
        <div class="fields">
            <p>
                <label for="x">x:</label>
                <input type="text" name="x" id="x" />
                <button type="button" class="action" id="setX">Set</button>
                <span id="xhint" class="hint"></span>
            </p>
            <p>
                <label for="y">y:</label>
                <input type="text" name="y" id="y" />
                <button type="button" class="action" id="setY">Set</button>
                <span id="yhint" class="hint"></span>
            </p>
            <p>
                <label for="color">color:</label>
                <input type="text" name="color" id="color" />
                <button type="button" class="action" id="setColor">Set</button>
            </p>
        </div>
    </div>
    <div class="footer">
        <button type="button" class="action" id="setXY">Set XY</button>
        <button type="button" class="action" id="setAll">Set All</button>
        <button type="button" class="action" id="getAll">Get All</button>
    </div>
</div>

<div id="boxParent"></div>

<script type="text/javascript">
// Get a new YUI instance 
YUI().use("node", "attribute", function(Y) {

    var boxParent = Y.one("#boxParent");

    // Setup a custom class with attribute support
    function Box(cfg) {
        this._createNode(cfg);
        
        // Attribute configuration
        var attrs = {
    
            "parent" : {
                value: null
            },

            "x" : {
                setter: function(val, name) {
                    // Pass through x value to xy
                    this.set("xy", [parseInt(val), this.get("y")]);
                },
    
                getter: function(val, name) {
                    // Get x value from xy
                    return this.get("xy")[0];
                }
            },
    
            "y" : {
                setter: function(val, name) {
                    // Pass through y value to xy
                    this.set("xy", [this.get("x"), parseInt(val)]);
                },
    
                getter: function() {
                    // Get y value from xy
                    return this.get("xy")[1];
                }
            },
    
            "xy" : {
                // Actual stored xy co-ordinates
                value: [0, 0],
    
                setter: function(val, name) {
                    // Constrain XY value to the parent element.
    
                    // Returns the constrained xy value, which will
                    // be the final value stored.
                    return this.constrain(val);
                },
    
                validator: function(val, name) {
                    // Ensure we only store a valid data value
                    return (Y.Lang.isArray(val) && val.length == 2 && Y.Lang.isNumber(val[0]) && Y.Lang.isNumber(val[1]));
                }
            },
    
            "color" : {
                value: "olive",
    
                getter: function(val, name) {
                    // Always normalize the returned value to 
                    // a hex color value,  even if the stored 
                    // value is a keyword, or an rgb value.
                    if (val) {
                        return Y.Color.toHex(val);
                    } else {
                        return null;
                    }
                },
    
                validator: function(val, name) {
                    // Ensure we only store rgb, hex or keyword values.
                    return (Y.Color.re_RGB.test(val) || Y.Color.re_hex.test(val) || Y.Color.KEYWORDS[val]); 
                }
            }
        };

        this.addAttrs(attrs, cfg);

        this._sync();
        this._bind();
    }

    Box.BUFFER = 5;

    // Create the box node
    Box.prototype._createNode = function() {
        this._node = Y.Node.create('<div class="yui3-box"><p>Positioned Box</p><p class="coord"></p><p class="color">None</p></div>');
    };

    // Update rendered state to match the attribute state
    Box.prototype._sync = function() {
        this._syncParent();
        this._syncXY();
        this._syncColor();
    };

    Box.prototype._syncParent = function() {
        this.get("parent").appendChild(this._node);
    };

    Box.prototype._syncXY = function() {
        this._node.setXY(this.get("xy"));
        this._node.one("p.coord").set("innerHTML", "[" + this.get("x") + "," + this.get("y") + "]");
    };

    Box.prototype._syncColor = function() {
        this._node.setStyle("backgroundColor", this.get("color"));
        this._node.one("p.color").set("innerHTML", this.get("color"));
    };

    // Bind listeners for attribute change events
    Box.prototype._bind = function() {

        // Reflect any changes in xy, to the rendered Node
        this.after("xyChange", this._syncXY);

        // Reflect any changes in color, to the rendered Node
        // and output the color value received from get
        this.after("colorChange", this._syncColor);

        // Append the rendered node to the parent provided
        this.after("parentChange", this._syncParent);

    };

    // Get min, max unconstrained values for X. Using Math.round to handle FF3's sub-pixel region values
    Box.prototype.getXConstraints = function() {
        var parentRegion = this.get("parent").get("region");
        return [Math.round(parentRegion.left + Box.BUFFER), Math.round(parentRegion.right - this._node.get("offsetWidth") - Box.BUFFER)];
    };

    // Get min, max unconstrained values for Y.  Using Math.round to handle FF3's sub-pixel region values
    Box.prototype.getYConstraints = function() {
        var parentRegion = this.get("parent").get("region");
        return [Math.round(parentRegion.top + Box.BUFFER), Math.round(parentRegion.bottom - this._node.get("offsetHeight") - Box.BUFFER)];
    };

    // Constrain the x,y value provided
    Box.prototype.constrain = function(val) {

        // If the X value places the box outside it's parent,
        // modify it's value to place the box inside it's parent.

        var xConstraints = this.getXConstraints();

        if (val[0] < xConstraints[0]) {
            val[0] = xConstraints[0];
        } else {
            if (val[0] > xConstraints[1]) {
                val[0] = xConstraints[1];
            }
        }

        // If the Y value places the box outside it's parent,
        // modify it's value to place the box inside it's parent.

        var yConstraints = this.getYConstraints();

        if (val[1] < yConstraints[0]) {
            val[1] = yConstraints[0];
        } else {
            if (val[1] > yConstraints[1]) {
                val[1] = yConstraints[1];
            }
        }

        return val;
    };


    Y.augment(Box, Y.Attribute);

    // ------

    // Create a new instance of Box
    var box = new Box({
        parent : boxParent 
    });

    // Set references to form controls
    var xTxt = Y.one("#x");
    var yTxt = Y.one("#y");
    var colorTxt = Y.one("#color");

    var xHint = Y.one("#xhint");
    var yHint = Y.one("#yhint");

    function getAll() {
        xTxt.set("value", box.get("x"));
        yTxt.set("value", box.get("y"));
        colorTxt.set("value", box.get("color"));
    }

    // Bind DOM events for Form Controls

    // Use event delegation for the action button clicks
    Y.delegate("click", function(e) {

        // Get Node target from the event object

        // We already know it's a button which has an action because
        // of our selector (button.action), so all we need to do is 
        // route it based on the id.
        var id = e.currentTarget.get("id");

        switch (id) {
            case "setXY":
                box.set("xy", [parseInt(xTxt.get("value")), parseInt(yTxt.get("value"))]);
                break;
            case "setX":
                box.set("x", parseInt(xTxt.get("value")));
                break;
            case "setY":
                box.set("y", parseInt(yTxt.get("value")));
                break;
            case "setColor":
                box.set("color", Y.Lang.trim(colorTxt.get("value")));
                break;
            case "setAll":
                box.set("xy", [parseInt(xTxt.get("value")), parseInt(yTxt.get("value"))]);
                box.set("color", Y.Lang.trim(colorTxt.get("value")));
                break;
            case "getAll":
                getAll();
                break;
            default:
                break;
        }

    }, "#attrs", "button.action");

    // Bind listeners to provide min, max unconstrained value hints for x, y
    // (focus/blur doesn't bubble, so bind individual listeners)
    Y.on("focus", function() {
        var minmax = box.getXConstraints();
        xHint.set("innerHTML", "Valid values: " + minmax[0] + " to " + minmax[1]);
    }, xTxt);

    Y.on("focus", function() {
        var minmax = box.getYConstraints();
        yHint.set("innerHTML", "Valid values: " + minmax[0] + " to " + minmax[1]);
    }, yTxt);

    Y.on("blur", function() {
        xHint.set("innerHTML", "");
    }, xTxt);

    Y.on("blur", function() {
        yHint.set("innerHTML", "");
    }, yTxt);

    getAll();
});
</script>
	
	<!--END SOURCE CODE FOR EXAMPLE =============================== -->
	
		
		</div>
	</div>			
	</div>
		
	<h3>Getter, Setter And Validator Functions</h3>

<p>Attribute lets you configure <code>getter</code> and <code>setter</code> functions for each attribute. These functions are invoked when the user calls Attribute's <code>get</code> and <code>set</code> methods, and provide a way to modify the value returned or the value stored respectively.</p>

<p>You can also define a <code>validator</code> function for each attribute, which is used to validate the final value before it gets stored.</p>

<p>All these functions receive the value and name of the attribute being set or retrieved, as shown in the example code below. The name is not used in this example, but is provided to support use cases where you may wish to share the same function between different attributes.</p>

<h4>Creating The Box Class - The X, Y And XY Attributes</h4>

<p>In this example, we'll set up a custom <code>Box</code> class representing a positionable element, with <code>x</code>, <code>y</code> and <code>xy</code> attributes.</p>

<p>Only the <code>xy</code> attribute will actually store the page co-ordinate position of the box. The <code>x</code> and <code>y</code> attributes provide the user a convenient way to set only one of the co-ordinates. 
However we don't want to store the actual values in the <code>x</code> and <code>y</code> attributes, to avoid having to constantly synchronize all three. 

The <code>getter</code> and <code>setter</code> functions provide us with an easy way to achieve this. We'll define <code>getter</code> and <code>setter</code> functions for both the <code>x</code> and <code>y</code> attributes, which simply pass through to the <code>xy</code> attribute to store and retrieve values:</p>

<div id="syntax-2cca7ed18b3474f781b945adfda5e50e" class="yui-syntax-highlight"><div class="numbers"><pre class="javascript" style="font-family:monospace;"><ol><li class="li1"><div class="de1"><span class="co1">// Setup a custom class with attribute support</span></div></li><li class="li1"><div class="de1"><span class="kw2">function</span> Box<span class="br0">&#40;</span>cfg<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    ...</div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="co1">// Attribute configuration</span></div></li><li class="li1"><div class="de1">    <span class="kw2">var</span> attrs <span class="sy0">=</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">        <span class="st0">&quot;parent&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span></div></li><li class="li2"><div class="de2">            value<span class="sy0">:</span> <span class="kw2">null</span></div></li><li class="li1"><div class="de1">        <span class="br0">&#125;</span><span class="sy0">,</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">        <span class="st0">&quot;x&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">            setter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li2"><div class="de2">                <span class="co1">// Pass through x value to xy</span></div></li><li class="li1"><div class="de1">                <span class="kw1">this</span>.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="sy0">,</span> <span class="br0">&#91;</span>parseInt<span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;y&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="br0">&#125;</span><span class="sy0">,</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">            getter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li2"><div class="de2">                <span class="co1">// Get x value from xy</span></div></li><li class="li1"><div class="de1">                <span class="kw1">return</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">        <span class="br0">&#125;</span><span class="sy0">,</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li2"><div class="de2">        <span class="st0">&quot;y&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">            setter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">                <span class="co1">// Pass through y value to xy</span></div></li><li class="li1"><div class="de1">                <span class="kw1">this</span>.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="sy0">,</span> <span class="br0">&#91;</span><span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;x&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="br0">&#125;</span><span class="sy0">,</span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">            getter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">                <span class="co1">// Get y value from xy</span></div></li><li class="li1"><div class="de1">                <span class="kw1">return</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="br0">&#125;</span></div></li><li class="li2"><div class="de2">        <span class="br0">&#125;</span><span class="sy0">,</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">        <span class="st0">&quot;xy&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">            <span class="co1">// Actual stored xy co-ordinates</span></div></li><li class="li1"><div class="de1">            value<span class="sy0">:</span> <span class="br0">&#91;</span><span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">,</span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">            setter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">                <span class="co1">// Constrain XY value to the parent element.</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">                <span class="co1">// Returns the constrained xy value, which will</span></div></li><li class="li2"><div class="de2">                <span class="co1">// be the final value stored.</span></div></li><li class="li1"><div class="de1">                <span class="kw1">return</span> <span class="kw1">this</span>.<span class="me1">constrain</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="br0">&#125;</span><span class="sy0">,</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">            validator<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li2"><div class="de2">                <span class="co1">// Ensure we only store a valid data value</span></div></li><li class="li1"><div class="de1">                <span class="kw1">return</span> <span class="br0">&#40;</span>Y.<span class="me1">Lang</span>.<span class="me1">isArray</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> </div></li><li class="li1"><div class="de1">                        val.<span class="me1">length</span> <span class="sy0">==</span> <span class="nu0">2</span> <span class="sy0">&amp;&amp;</span> </div></li><li class="li1"><div class="de1">                        Y.<span class="me1">Lang</span>.<span class="me1">isNumber</span><span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> Y.<span class="me1">Lang</span>.<span class="me1">isNumber</span><span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="br0">&#125;</span></div></li><li class="li2"><div class="de2">        <span class="br0">&#125;</span><span class="sy0">,</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    ...</div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="kw1">this</span>.<span class="me1">addAttrs</span><span class="br0">&#40;</span>attrs<span class="sy0">,</span> cfg<span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">    ...</div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span></div></li></ol></pre></div><div class="nonumbers"><pre class="javascript" style="font-family:monospace;"><span class="co1">// Setup a custom class with attribute support</span>
<span class="kw2">function</span> Box<span class="br0">&#40;</span>cfg<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
    ...
&nbsp;
    <span class="co1">// Attribute configuration</span>
    <span class="kw2">var</span> attrs <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp;
        <span class="st0">&quot;parent&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span>
            value<span class="sy0">:</span> <span class="kw2">null</span>
        <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
        <span class="st0">&quot;x&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span>
            setter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="co1">// Pass through x value to xy</span>
                <span class="kw1">this</span>.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="sy0">,</span> <span class="br0">&#91;</span>parseInt<span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;y&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
            getter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="co1">// Get x value from xy</span>
                <span class="kw1">return</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span>
        <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
        <span class="st0">&quot;y&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span>
            setter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="co1">// Pass through y value to xy</span>
                <span class="kw1">this</span>.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="sy0">,</span> <span class="br0">&#91;</span><span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;x&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
            getter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="co1">// Get y value from xy</span>
                <span class="kw1">return</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span>
        <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
        <span class="st0">&quot;xy&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span>
            <span class="co1">// Actual stored xy co-ordinates</span>
            value<span class="sy0">:</span> <span class="br0">&#91;</span><span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">,</span>
&nbsp;
            setter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="co1">// Constrain XY value to the parent element.</span>
&nbsp;
                <span class="co1">// Returns the constrained xy value, which will</span>
                <span class="co1">// be the final value stored.</span>
                <span class="kw1">return</span> <span class="kw1">this</span>.<span class="me1">constrain</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
            validator<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="co1">// Ensure we only store a valid data value</span>
                <span class="kw1">return</span> <span class="br0">&#40;</span>Y.<span class="me1">Lang</span>.<span class="me1">isArray</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> 
                        val.<span class="me1">length</span> <span class="sy0">==</span> <span class="nu0">2</span> <span class="sy0">&amp;&amp;</span> 
                        Y.<span class="me1">Lang</span>.<span class="me1">isNumber</span><span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> Y.<span class="me1">Lang</span>.<span class="me1">isNumber</span><span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span>
        <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
    ...
&nbsp;
    <span class="kw1">this</span>.<span class="me1">addAttrs</span><span class="br0">&#40;</span>attrs<span class="sy0">,</span> cfg<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    ...
<span class="br0">&#125;</span></pre></div><textarea id="syntax-2cca7ed18b3474f781b945adfda5e50e-plain">// Setup a custom class with attribute support
function Box(cfg) {

    ...
          
    // Attribute configuration
    var attrs = {

        "parent" : {
            value: null
        },

        "x" : {
            setter: function(val, name) {
                // Pass through x value to xy
                this.set("xy", [parseInt(val), this.get("y")]);
            },

            getter: function(val, name) {
                // Get x value from xy
                return this.get("xy")[0];
            }
        },

        "y" : {
            setter: function(val, name) {
                // Pass through y value to xy
                this.set("xy", [this.get("x"), parseInt(val)]);
            },

            getter: function() {
                // Get y value from xy
                return this.get("xy")[1];
            }
        },

        "xy" : {
            // Actual stored xy co-ordinates
            value: [0, 0],

            setter: function(val, name) {
                // Constrain XY value to the parent element.

                // Returns the constrained xy value, which will
                // be the final value stored.
                return this.constrain(val);
            },

            validator: function(val, name) {
                // Ensure we only store a valid data value
                return (Y.Lang.isArray(val) && 
                        val.length == 2 && 
                        Y.Lang.isNumber(val[0]) && Y.Lang.isNumber(val[1]));
            }
        },

    ...

    this.addAttrs(attrs, cfg);

    ...
}</textarea></div>
<p>The <code>validator</code> function for <code>xy</code> ensures that only valid values finally end up being stored.</p>

<p>The <code>xy</code> attribute also has a <code>setter</code> function configured, which makes sure that the box is always constrained to it's parent element. The <code>constrain</code> method which it delegates to, takes the xy value the user is trying to set and returns a constrained value if the x or y values fall outside the parent box. The value which is returned by the <code>setter</code> is the value which is ultimately stored for the <code>xy</code> attribute:</p>

<div id="syntax-0935da5327bce56ff983fa943fde9f93" class="yui-syntax-highlight"><div class="numbers"><pre class="javascript" style="font-family:monospace;"><ol><li class="li1"><div class="de1"><span class="co1">// Get min, max unconstrained values for X. </span></div></li><li class="li1"><div class="de1"><span class="co1">// Using Math.round to handle FF3's sub-pixel region values</span></div></li><li class="li1"><div class="de1">Box.<span class="me1">prototype</span>.<span class="me1">getXConstraints</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">    <span class="kw2">var</span> parentRegion <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;parent&quot;</span><span class="br0">&#41;</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;region&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">    <span class="kw1">return</span> <span class="br0">&#91;</span>Math.<span class="me1">round</span><span class="br0">&#40;</span>parentRegion.<span class="me1">left</span> <span class="sy0">+</span> Box.<span class="me1">BUFFER</span><span class="br0">&#41;</span><span class="sy0">,</span> </div></li><li class="li1"><div class="de1">            Math.<span class="me1">round</span><span class="br0">&#40;</span>parentRegion.<span class="me1">right</span> <span class="sy0">-</span> <span class="kw1">this</span>._node.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;offsetWidth&quot;</span><span class="br0">&#41;</span> <span class="sy0">-</span> Box.<span class="me1">BUFFER</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="co1">// Get min, max unconstrained values for Y.  </span></div></li><li class="li2"><div class="de2"><span class="co1">// Using Math.round to handle FF3's sub-pixel region values</span></div></li><li class="li1"><div class="de1">Box.<span class="me1">prototype</span>.<span class="me1">getYConstraints</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">    <span class="kw2">var</span> parentRegion <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;parent&quot;</span><span class="br0">&#41;</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;region&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">return</span> <span class="br0">&#91;</span>Math.<span class="me1">round</span><span class="br0">&#40;</span>parentRegion.<span class="me1">top</span> <span class="sy0">+</span> Box.<span class="me1">BUFFER</span><span class="br0">&#41;</span><span class="sy0">,</span> </div></li><li class="li1"><div class="de1">            Math.<span class="me1">round</span><span class="br0">&#40;</span>parentRegion.<span class="me1">bottom</span> <span class="sy0">-</span> <span class="kw1">this</span>._node.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;offsetHeight&quot;</span><span class="br0">&#41;</span> <span class="sy0">-</span> Box.<span class="me1">BUFFER</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2"><span class="br0">&#125;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="co1">// Constrains given x,y values</span></div></li><li class="li1"><div class="de1">Box.<span class="me1">prototype</span>.<span class="me1">constrain</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li2"><div class="de2">    <span class="co1">// If the X value places the box outside it's parent,</span></div></li><li class="li1"><div class="de1">    <span class="co1">// modify it's value to place the box inside it's parent.</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="kw2">var</span> xConstraints <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">getXConstraints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li2"><div class="de2">    <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">&lt;</span> xConstraints<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">        val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">=</span> xConstraints<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">&gt;</span> xConstraints<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">            val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">=</span> xConstraints<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">        <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">    <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="co1">// If the Y value places the box outside it's parent,</span></div></li><li class="li1"><div class="de1">    <span class="co1">// modify it's value to place the box inside it's parent.</span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="kw2">var</span> yConstraints <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">getYConstraints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&lt;</span> yConstraints<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">        val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> yConstraints<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&gt;</span> yConstraints<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">            val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> yConstraints<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">        <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">    <span class="br0">&#125;</span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="kw1">return</span> val<span class="sy0">;</span></div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span><span class="sy0">;</span></div></li></ol></pre></div><div class="nonumbers"><pre class="javascript" style="font-family:monospace;"><span class="co1">// Get min, max unconstrained values for X. </span>
<span class="co1">// Using Math.round to handle FF3's sub-pixel region values</span>
Box.<span class="me1">prototype</span>.<span class="me1">getXConstraints</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">var</span> parentRegion <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;parent&quot;</span><span class="br0">&#41;</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;region&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">return</span> <span class="br0">&#91;</span>Math.<span class="me1">round</span><span class="br0">&#40;</span>parentRegion.<span class="me1">left</span> <span class="sy0">+</span> Box.<span class="me1">BUFFER</span><span class="br0">&#41;</span><span class="sy0">,</span> 
            Math.<span class="me1">round</span><span class="br0">&#40;</span>parentRegion.<span class="me1">right</span> <span class="sy0">-</span> <span class="kw1">this</span>._node.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;offsetWidth&quot;</span><span class="br0">&#41;</span> <span class="sy0">-</span> Box.<span class="me1">BUFFER</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Get min, max unconstrained values for Y.  </span>
<span class="co1">// Using Math.round to handle FF3's sub-pixel region values</span>
Box.<span class="me1">prototype</span>.<span class="me1">getYConstraints</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">var</span> parentRegion <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;parent&quot;</span><span class="br0">&#41;</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;region&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">return</span> <span class="br0">&#91;</span>Math.<span class="me1">round</span><span class="br0">&#40;</span>parentRegion.<span class="me1">top</span> <span class="sy0">+</span> Box.<span class="me1">BUFFER</span><span class="br0">&#41;</span><span class="sy0">,</span> 
            Math.<span class="me1">round</span><span class="br0">&#40;</span>parentRegion.<span class="me1">bottom</span> <span class="sy0">-</span> <span class="kw1">this</span>._node.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;offsetHeight&quot;</span><span class="br0">&#41;</span> <span class="sy0">-</span> Box.<span class="me1">BUFFER</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Constrains given x,y values</span>
Box.<span class="me1">prototype</span>.<span class="me1">constrain</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
    <span class="co1">// If the X value places the box outside it's parent,</span>
    <span class="co1">// modify it's value to place the box inside it's parent.</span>
&nbsp;
    <span class="kw2">var</span> xConstraints <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">getXConstraints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">&lt;</span> xConstraints<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">=</span> xConstraints<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
        <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">&gt;</span> xConstraints<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">=</span> xConstraints<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="co1">// If the Y value places the box outside it's parent,</span>
    <span class="co1">// modify it's value to place the box inside it's parent.</span>
&nbsp;
    <span class="kw2">var</span> yConstraints <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">getYConstraints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&lt;</span> yConstraints<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> yConstraints<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
        <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&gt;</span> yConstraints<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            val<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> yConstraints<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">return</span> val<span class="sy0">;</span>
<span class="br0">&#125;</span><span class="sy0">;</span></pre></div><textarea id="syntax-0935da5327bce56ff983fa943fde9f93-plain">// Get min, max unconstrained values for X. 
// Using Math.round to handle FF3's sub-pixel region values
Box.prototype.getXConstraints = function() {
    var parentRegion = this.get("parent").get("region");
    return [Math.round(parentRegion.left + Box.BUFFER), 
            Math.round(parentRegion.right - this._node.get("offsetWidth") - Box.BUFFER)];
};

// Get min, max unconstrained values for Y.  
// Using Math.round to handle FF3's sub-pixel region values
Box.prototype.getYConstraints = function() {
    var parentRegion = this.get("parent").get("region");
    return [Math.round(parentRegion.top + Box.BUFFER), 
            Math.round(parentRegion.bottom - this._node.get("offsetHeight") - Box.BUFFER)];
};

// Constrains given x,y values
Box.prototype.constrain = function(val) {

    // If the X value places the box outside it's parent,
    // modify it's value to place the box inside it's parent.

    var xConstraints = this.getXConstraints();

    if (val[0] < xConstraints[0]) {
        val[0] = xConstraints[0];
    } else {
        if (val[0] > xConstraints[1]) {
            val[0] = xConstraints[1];
        }
    }

    // If the Y value places the box outside it's parent,
    // modify it's value to place the box inside it's parent.

    var yConstraints = this.getYConstraints();

    if (val[1] < yConstraints[0]) {
        val[1] = yConstraints[0];
    } else {
        if (val[1] > yConstraints[1]) {
            val[1] = yConstraints[1];
        }
    }

    return val;
};</textarea></div>
<p>The <code>setter</code>, <code>getter</code> and <code>validator</code> functions are invoked with the host object as the context, so that they can refer to the host object using "<code>this</code>", as we see in the <code>setter</code> function for <code>xy</code>.</p>

<h4>The Color Attribute - Normalizing Stored Values Through Get</h4>

<p>The <code>Box</code> class also has a <code>color</code> attribute which also has a <code>getter</code> and <code>validator</code> functions defined:</p>

<div id="syntax-bad4c49490f3169b21300b537b175244" class="yui-syntax-highlight"><div class="numbers"><pre class="javascript" style="font-family:monospace;"><ol><li class="li1"><div class="de1">...</div></li><li class="li1"><div class="de1"><span class="st0">&quot;color&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">    value<span class="sy0">:</span> <span class="st0">&quot;olive&quot;</span><span class="sy0">,</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li2"><div class="de2">    getter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">return</span> Y.<span class="me1">Color</span>.<span class="me1">toHex</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">        <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">return</span> <span class="kw2">null</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">        <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">    <span class="br0">&#125;</span><span class="sy0">,</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    validator<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">return</span> <span class="br0">&#40;</span>Y.<span class="me1">Color</span>.<span class="me1">re_RGB</span>.<span class="me1">test</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span> <span class="sy0">||</span> Y.<span class="me1">Color</span>.<span class="me1">re_hex</span>.<span class="me1">test</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span> </div></li><li class="li2"><div class="de2">                    <span class="sy0">||</span> Y.<span class="me1">Color</span>.<span class="me1">KEYWORDS</span><span class="br0">&#91;</span>val<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">    <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">...</div></li></ol></pre></div><div class="nonumbers"><pre class="javascript" style="font-family:monospace;">...
<span class="st0">&quot;color&quot;</span> <span class="sy0">:</span> <span class="br0">&#123;</span>
    value<span class="sy0">:</span> <span class="st0">&quot;olive&quot;</span><span class="sy0">,</span>
&nbsp;
    getter<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">if</span> <span class="br0">&#40;</span>val<span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="kw1">return</span> Y.<span class="me1">Color</span>.<span class="me1">toHex</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
            <span class="kw1">return</span> <span class="kw2">null</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
    validator<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>val<span class="sy0">,</span> <span class="kw3">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">return</span> <span class="br0">&#40;</span>Y.<span class="me1">Color</span>.<span class="me1">re_RGB</span>.<span class="me1">test</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span> <span class="sy0">||</span> Y.<span class="me1">Color</span>.<span class="me1">re_hex</span>.<span class="me1">test</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span> 
                    <span class="sy0">||</span> Y.<span class="me1">Color</span>.<span class="me1">KEYWORDS</span><span class="br0">&#91;</span>val<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
...</pre></div><textarea id="syntax-bad4c49490f3169b21300b537b175244-plain">...
"color" : {
    value: "olive",

    getter: function(val, name) {
        if (val) {
            return Y.Color.toHex(val);
        } else {
            return null;
        }
    },

    validator: function(val, name) {
        return (Y.Color.re_RGB.test(val) || Y.Color.re_hex.test(val) 
                    || Y.Color.KEYWORDS[val]);
    }
}
...</textarea></div>
<p>The role of the <code>getter</code> handler in this case is to normalize the actual stored value of the <code>color</code> attribute, so that users always receive the hex value, regardless of the actual value stored, which maybe a color keyword (e.g. <code>"red"</code>), an rgb value (e.g.<code>rbg(255,0,0)</code>), or a hex value (<code>#ff0000</code>). The <code>validator</code> ensures the the stored value is one of these three formats.</p>

<h4>Syncing Changes Using Attribute Change Events</h4>

<p>Another interesting aspect of this example, is it's use of attribute change events to listen for changes to the attribute values. <code>Box</code>'s <code>_bind</code> method configures a set of attribute change event listeners which monitor changes to the <code>xy</code>, <code>color</code> and <code>parent</code> attributes and update the rendered DOM for the Box in response:</p>

<div id="syntax-e54a30f7c47941952f5f557c3c43c690" class="yui-syntax-highlight"><div class="numbers"><pre class="javascript" style="font-family:monospace;"><ol><li class="li1"><div class="de1"><span class="co1">// Bind listeners for attribute change events</span></div></li><li class="li1"><div class="de1">Box.<span class="me1">prototype</span>._bind <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="co1">// Reflect any changes in xy, to the rendered Node</span></div></li><li class="li2"><div class="de2">    <span class="kw1">this</span>.<span class="me1">after</span><span class="br0">&#40;</span><span class="st0">&quot;xyChange&quot;</span><span class="sy0">,</span> <span class="kw1">this</span>._syncXY<span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="co1">// Reflect any changes in color, to the rendered Node</span></div></li><li class="li1"><div class="de1">    <span class="co1">// and output the color value received from get</span></div></li><li class="li1"><div class="de1">    <span class="kw1">this</span>.<span class="me1">after</span><span class="br0">&#40;</span><span class="st0">&quot;colorChange&quot;</span><span class="sy0">,</span> <span class="kw1">this</span>._syncColor<span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="co1">// Append the rendered node to the parent provided</span></div></li><li class="li1"><div class="de1">    <span class="kw1">this</span>.<span class="me1">after</span><span class="br0">&#40;</span><span class="st0">&quot;parentChange&quot;</span><span class="sy0">,</span> <span class="kw1">this</span>._syncParent<span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span><span class="sy0">;</span></div></li></ol></pre></div><div class="nonumbers"><pre class="javascript" style="font-family:monospace;"><span class="co1">// Bind listeners for attribute change events</span>
Box.<span class="me1">prototype</span>._bind <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
    <span class="co1">// Reflect any changes in xy, to the rendered Node</span>
    <span class="kw1">this</span>.<span class="me1">after</span><span class="br0">&#40;</span><span class="st0">&quot;xyChange&quot;</span><span class="sy0">,</span> <span class="kw1">this</span>._syncXY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// Reflect any changes in color, to the rendered Node</span>
    <span class="co1">// and output the color value received from get</span>
    <span class="kw1">this</span>.<span class="me1">after</span><span class="br0">&#40;</span><span class="st0">&quot;colorChange&quot;</span><span class="sy0">,</span> <span class="kw1">this</span>._syncColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// Append the rendered node to the parent provided</span>
    <span class="kw1">this</span>.<span class="me1">after</span><span class="br0">&#40;</span><span class="st0">&quot;parentChange&quot;</span><span class="sy0">,</span> <span class="kw1">this</span>._syncParent<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="br0">&#125;</span><span class="sy0">;</span></pre></div><textarea id="syntax-e54a30f7c47941952f5f557c3c43c690-plain">// Bind listeners for attribute change events
Box.prototype._bind = function() {

    // Reflect any changes in xy, to the rendered Node
    this.after("xyChange", this._syncXY);

    // Reflect any changes in color, to the rendered Node
    // and output the color value received from get
    this.after("colorChange", this._syncColor);

    // Append the rendered node to the parent provided
    this.after("parentChange", this._syncParent);

};</textarea></div>
<p>Since only <code>xy</code> stores the final co-ordinates, we don't need to monitor the <code>x</code> and <code>y</code> attributes individually for changes.</p>

<h4>DOM Event Listeners And Delegation</h4>

<p>Although not an integral part of the example, it's worth highlighting the code which is used to setup the DOM event listeners for the form elements used by the example:</p>

<div id="syntax-7fca5dcaf24d5a7c36d75ed51df28d23" class="yui-syntax-highlight"><div class="numbers"><pre class="javascript" style="font-family:monospace;"><ol><li class="li1"><div class="de1"><span class="co1">// Set references to form controls</span></div></li><li class="li1"><div class="de1"><span class="kw2">var</span> xTxt <span class="sy0">=</span> Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#x&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1"><span class="kw2">var</span> yTxt <span class="sy0">=</span> Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#y&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1"><span class="kw2">var</span> colorTxt <span class="sy0">=</span> Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#color&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1"><span class="co1">// Use event delegation for the action button clicks</span></div></li><li class="li1"><div class="de1">Y.<span class="me1">delegate</span><span class="br0">&#40;</span><span class="st0">&quot;click&quot;</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="co1">// Get Node target from the event object. </span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="co1">// We already know it's a button which has an action because</span></div></li><li class="li1"><div class="de1">    <span class="co1">// of our selector (button.action), so all we need to do is </span></div></li><li class="li1"><div class="de1">    <span class="co1">// route it based on the id.</span></div></li><li class="li1"><div class="de1">    <span class="kw2">var</span> id <span class="sy0">=</span> e.<span class="me1">currentTarget</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;id&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">&nbsp;</div></li><li class="li1"><div class="de1">    <span class="kw1">switch</span> <span class="br0">&#40;</span>id<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">case</span> <span class="st0">&quot;setXY&quot;</span><span class="sy0">:</span></div></li><li class="li1"><div class="de1">            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="sy0">,</span> <span class="br0">&#91;</span>parseInt<span class="br0">&#40;</span>xTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>yTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">break</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">        <span class="kw1">case</span> <span class="st0">&quot;setX&quot;</span><span class="sy0">:</span></div></li><li class="li1"><div class="de1">            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;x&quot;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>xTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">break</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">case</span> <span class="st0">&quot;setY&quot;</span><span class="sy0">:</span></div></li><li class="li1"><div class="de1">            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;y&quot;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>yTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">            <span class="kw1">break</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">case</span> <span class="st0">&quot;setColor&quot;</span><span class="sy0">:</span></div></li><li class="li1"><div class="de1">            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;color&quot;</span><span class="sy0">,</span> Y.<span class="me1">Lang</span>.<span class="me1">trim</span><span class="br0">&#40;</span>colorTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">break</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">case</span> <span class="st0">&quot;setAll&quot;</span><span class="sy0">:</span></div></li><li class="li2"><div class="de2">            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="sy0">,</span> <span class="br0">&#91;</span>parseInt<span class="br0">&#40;</span>xTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>yTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;color&quot;</span><span class="sy0">,</span> Y.<span class="me1">Lang</span>.<span class="me1">trim</span><span class="br0">&#40;</span>colorTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">break</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">case</span> <span class="st0">&quot;getAll&quot;</span><span class="sy0">:</span></div></li><li class="li1"><div class="de1">            getAll<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li2"><div class="de2">            <span class="kw1">break</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">        <span class="kw2">default</span><span class="sy0">:</span></div></li><li class="li1"><div class="de1">            <span class="kw1">break</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">    <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li2"><div class="de2"><span class="br0">&#125;</span><span class="sy0">,</span> <span class="st0">&quot;#attrs&quot;</span><span class="sy0">,</span> <span class="st0">&quot;click&quot;</span><span class="sy0">,</span> <span class="st0">&quot;button.action&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li></ol></pre></div><div class="nonumbers"><pre class="javascript" style="font-family:monospace;"><span class="co1">// Set references to form controls</span>
<span class="kw2">var</span> xTxt <span class="sy0">=</span> Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#x&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">var</span> yTxt <span class="sy0">=</span> Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#y&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">var</span> colorTxt <span class="sy0">=</span> Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#color&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Use event delegation for the action button clicks</span>
Y.<span class="me1">delegate</span><span class="br0">&#40;</span><span class="st0">&quot;click&quot;</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
    <span class="co1">// Get Node target from the event object. </span>
&nbsp;
    <span class="co1">// We already know it's a button which has an action because</span>
    <span class="co1">// of our selector (button.action), so all we need to do is </span>
    <span class="co1">// route it based on the id.</span>
    <span class="kw2">var</span> id <span class="sy0">=</span> e.<span class="me1">currentTarget</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;id&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">switch</span> <span class="br0">&#40;</span>id<span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">case</span> <span class="st0">&quot;setXY&quot;</span><span class="sy0">:</span>
            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="sy0">,</span> <span class="br0">&#91;</span>parseInt<span class="br0">&#40;</span>xTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>yTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="kw1">break</span><span class="sy0">;</span>
        <span class="kw1">case</span> <span class="st0">&quot;setX&quot;</span><span class="sy0">:</span>
            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;x&quot;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>xTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="kw1">break</span><span class="sy0">;</span>
        <span class="kw1">case</span> <span class="st0">&quot;setY&quot;</span><span class="sy0">:</span>
            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;y&quot;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>yTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="kw1">break</span><span class="sy0">;</span>
        <span class="kw1">case</span> <span class="st0">&quot;setColor&quot;</span><span class="sy0">:</span>
            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;color&quot;</span><span class="sy0">,</span> Y.<span class="me1">Lang</span>.<span class="me1">trim</span><span class="br0">&#40;</span>colorTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="kw1">break</span><span class="sy0">;</span>
        <span class="kw1">case</span> <span class="st0">&quot;setAll&quot;</span><span class="sy0">:</span>
            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;xy&quot;</span><span class="sy0">,</span> <span class="br0">&#91;</span>parseInt<span class="br0">&#40;</span>xTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span> parseInt<span class="br0">&#40;</span>yTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            box.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;color&quot;</span><span class="sy0">,</span> Y.<span class="me1">Lang</span>.<span class="me1">trim</span><span class="br0">&#40;</span>colorTxt.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;value&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="kw1">break</span><span class="sy0">;</span>
        <span class="kw1">case</span> <span class="st0">&quot;getAll&quot;</span><span class="sy0">:</span>
            getAll<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="kw1">break</span><span class="sy0">;</span>
        <span class="kw2">default</span><span class="sy0">:</span>
            <span class="kw1">break</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
<span class="br0">&#125;</span><span class="sy0">,</span> <span class="st0">&quot;#attrs&quot;</span><span class="sy0">,</span> <span class="st0">&quot;click&quot;</span><span class="sy0">,</span> <span class="st0">&quot;button.action&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div><textarea id="syntax-7fca5dcaf24d5a7c36d75ed51df28d23-plain">// Set references to form controls
var xTxt = Y.one("#x");
var yTxt = Y.one("#y");
var colorTxt = Y.one("#color");

// Use event delegation for the action button clicks
Y.delegate("click", function(e) {

    // Get Node target from the event object. 

    // We already know it's a button which has an action because
    // of our selector (button.action), so all we need to do is 
    // route it based on the id.
    var id = e.currentTarget.get("id");

    switch (id) {
        case "setXY":
            box.set("xy", [parseInt(xTxt.get("value")), parseInt(yTxt.get("value"))]);
            break;
        case "setX":
            box.set("x", parseInt(xTxt.get("value")));
            break;
        case "setY":
            box.set("y", parseInt(yTxt.get("value")));
            break;
        case "setColor":
            box.set("color", Y.Lang.trim(colorTxt.get("value")));
            break;
        case "setAll":
            box.set("xy", [parseInt(xTxt.get("value")), parseInt(yTxt.get("value"))]);
            box.set("color", Y.Lang.trim(colorTxt.get("value")));
            break;
        case "getAll":
            getAll();
            break;
        default:
            break;
    }

}, "#attrs", "click", "button.action");</textarea></div>
<p>Rather than attach individual listeners to each button, the above code uses YUI 3's <code>delegate</code> support, to listen for clicks from <code>buttons</code> with an <code>action</code> class which bubble up to the <code>attrs</code> element.</p>
<p>The delegate listener uses the <a href="../../api/DOMEventFacade.html">Event Facade</a> which normalizes cross-browser access to DOM event properties, such as <code>currentTarget</code>, to route to the appropriate button handler. Note the use of selector syntax when we specify the elements for the listener (e.g. <code>#attrs</code>, <code>button.actions</code>) and the use of the <a href="../../api/Node.html">Node</a> facade when dealing with references to HTML elements (e.g. <code>xTxt, yTxt, colorTxt</code>).</p>
				</div>
				<div class="yui-u sidebar">
					
				
					<div id="examples" class="mod box4">
                        <div class="hd">
						<h4>
    Attribute Examples:</h4>
                        </div>
						<div class="bd">
							<ul>
								<li><a href='../attribute/attribute-basic.html'>Basic Attribute Configuration</a></li><li><a href='../attribute/attribute-rw.html'>Read-Only and Write-Once Attributes</a></li><li><a href='../attribute/attribute-event.html'>Attribute Change Events</a></li><li><a href='../attribute/attribute-basic-speeddate.html'>Attribute Based Speed Dating</a></li><li><a href='../attribute/attribute-event-speeddate.html'>Attribute Event Based Speed Dating</a></li><li class='selected'><a href='../attribute/attribute-getset.html'>Attribute Getters, Setters and Validators</a></li>							</ul>
						</div>
					</div>
					
					<div class="mod box4">
                        <div class="hd">
						<h4>More Attribute Resources:</h4>
                        </div>
                        <div class="bd">
						<ul>
							<!-- <li><a href="http://developer.yahoo.com/yui/attribute/">User's Guide</a> (external)</li> -->
<li><a href="../../api/module_attribute.html">API Documentation</a></li></ul>
                        </div>
					</div>
			  </div>
		</div>
		
		</div>
	</div>


<div class="yui-b toc3" id="tocWrapper">
<!-- TABLE OF CONTENTS -->
<div id="toc">
	
<ul>
<li class="sect first">YUI 3 Resources</li><li class="item"><a title="YUI 3 -- Yahoo! User Interface (YUI) Library" href="http://developer.yahoo.com/yui/3/">YUI 3 Web Site</a></li><li class="item"><a title="Examples of every YUI utility and control in action" href="../../examples/">YUI 3 Examples</a></li><li class="item"><a title="Instantly searchable API documentation for the entire YUI library." href="../../api/">YUI 3 API Docs</a></li><li class="item"><a title="YUI 3 Dependency Configurator -- configure your custom YUI implementation" href="http://developer.yahoo.com/yui/3/configurator/index.html">YUI 3 Dependency Configurator</a></li><li class="item"><a title="The YUI 3 Forum on YUILibrary.com" href="http://yuilibrary.com/forum/viewforum.php?f=15">YUI 3 Forums (external)</a></li><li class="item"><a title="Found a bug or a missing feature? Let us know on YUILibrary.com." href="http://developer.yahoo.com/yui/articles/reportingbugs/">Bug Reports/Feature Requests</a></li><li class="item"><a title="YUI is free and open, offered under a BSD license." href="http://developer.yahoo.com/yui/license.html">YUI License</a></li><li class="item"><a title="Download and fork the YUI project on GitHub" href="http://github.com/yui">YUI on Github</a></li><li class="item"><a title="The Yahoo! User Interface Blog" href="http://yuiblog.com">YUI Blog (external)</a></li><li class="sect">YUI 3 Core - Examples</li><li class="item"><a title="YUI Global Object - Functional Examples" href="../../examples/yui/index.html">YUI Global Object</a></li><li class="item"><a title="Event - Functional Examples" href="../../examples/event/index.html">Event</a></li><li class="item"><a title="Node - Functional Examples" href="../../examples/node/index.html">Node</a></li><li class="sect">YUI 3 Component Infrastructure - Examples</li><li class="selected "><a title="Attribute - Functional Examples" href="../../examples/attribute/index.html">Attribute</a></li><li class="item"><a title="Plugin - Functional Examples" href="../../examples/plugin/index.html">Plugin</a></li><li class="item"><a title="Widget - Functional Examples" href="../../examples/widget/index.html">Widget</a></li><li class="sect">YUI 3 Utilities - Examples</li><li class="item"><a title="Animation - Functional Examples" href="../../examples/anim/index.html">Animation</a></li><li class="item"><a title="AsyncQueue - Functional Examples" href="../../examples/async-queue/index.html">AsyncQueue</a></li><li class="item"><a title="Browser History - Functional Examples" href="../../examples/history/index.html">Browser History</a></li><li class="item"><a title="Cache - Functional Examples" href="../../examples/cache/index.html">Cache</a></li><li class="item"><a title="Cookie - Functional Examples" href="../../examples/cookie/index.html">Cookie</a></li><li class="item"><a title="DataSchema - Functional Examples" href="../../examples/dataschema/index.html">DataSchema <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="DataSource - Functional Examples" href="../../examples/datasource/index.html">DataSource <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="DataType - Functional Examples" href="../../examples/datatype/index.html">DataType <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="Drag &amp; Drop - Functional Examples" href="../../examples/dd/index.html">Drag &amp; Drop</a></li><li class="item"><a title="Get - Functional Examples" href="../../examples/get/index.html">Get</a></li><li class="item"><a title="ImageLoader - Functional Examples" href="../../examples/imageloader/index.html">ImageLoader</a></li><li class="item"><a title="Internationalization - Functional Examples" href="../../examples/intl/index.html">Internationalization <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="IO - Functional Examples" href="../../examples/io/index.html">IO</a></li><li class="item"><a title="JSON (JavaScript Object Notation) - Functional Examples" href="../../examples/json/index.html">JSON</a></li><li class="item"><a title="Stylesheet - Functional Examples" href="../../examples/stylesheet/index.html">Stylesheet</a></li><li class="sect">YUI 3 Widgets - Examples</li><li class="item"><a title="Overlay - Functional Examples" href="../../examples/overlay/index.html">Overlay <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="Slider - Functional Examples" href="../../examples/slider/index.html">Slider <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="Tabview - Functional Examples" href="../../examples/tabview/index.html">Tabview <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="sect">YUI 3 Node Plugins - Examples</li><li class="item"><a title="FocusManager Node Plugin - Functional Examples" href="../../examples/node-focusmanager/index.html">FocusManager Node Plugin <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="MenuNav Node Plugin - Functional Examples" href="../../examples/node-menunav/index.html">MenuNav Node Plugin <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="sect">YUI 3 CSS - Examples</li><li class="item"><a title="YUI CSS Reset - Functional Examples" href="../../examples/cssreset/index.html">CSS Reset</a></li><li class="item"><a title="YUI Fonts - Functional Examples" href="../../examples/cssfonts/index.html">CSS Fonts</a></li><li class="item"><a title="YUI Base - Functional Examples" href="../../examples/cssbase/index.html">CSS Base</a></li><li class="sect">YUI 3 Developer Tools - Examples</li><li class="item"><a title="Console - Functional Examples" href="../../examples/console/index.html">Console <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="Console Filters Plugin- Functional Examples" href="../../examples/console-filters/index.html">Plugin.ConsoleFilters <img alt='beta' src='http://l.yimg.com/a/i/not/beta_1.gif'></a></li><li class="item"><a title="Profiler - Functional Examples" href="../../examples/profiler/index.html">Profiler</a></li><li class="item"><a title="Test - Functional Examples" href="../../examples/test/index.html">Test</a></li><li class="sect">Other Useful YUI 3 Resources</li><li class="item"><a title="Answers to Frequently Asked Questions about the YUI Library" href="http://developer.yahoo.com/yui/articles/faq/">YUI FAQ (external)</a></li><li class="item"><a title="Yahoo!'s philosophy of Graded Browser Support" href="http://developer.yahoo.com/yui/articles/gbs/">Graded Browser Support (external)</a></li><li class="item"><a title="Videos and podcasts from the YUI Team and from the Yahoo! frontend engineering community." href="http://developer.yahoo.com/yui/theater/">YUI Theater (external)</a></li></ul>
</div>
</div>
	</div><!--closes bd-->

	<div id="ft">
        <p class="first">Copyright &copy; 2010 Yahoo! Inc. All rights reserved.</p>
        <p><a href="http://privacy.yahoo.com/privacy/us/devel/index.html">Privacy Policy</a> - 
            <a href="http://docs.yahoo.com/info/terms/">Terms of Service</a> - 
            <a href="http://docs.yahoo.com/info/copyright/copyright.html">Copyright Policy</a> - 
            <a href="http://careers.yahoo.com/">Job Openings</a></p>
	</div>
</div>
<script language="javascript"> 
var yuiConfig = {};
</script>
<script src="../../assets/syntax.js"></script>
<script src="../../assets/dpSyntaxHighlighter.js"></script>
<script language="javascript"> 
dp.SyntaxHighlighter.HighlightAll('code'); 
</script>
</body>
</html>
